package hh.util.bean.codegen;

import hh.util.StringUtil;
import hh.util.bean.ClassUtil;
import hh.compile.CompileUtil;
import hh.util.bean.GetAndSet;

import java.lang.reflect.Field;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author huanghuai
 * @date 2020/10/27
 */
public class GetAndSetFactory {

    static final AtomicInteger index = new AtomicInteger(0);
    static final String pkg = "hh.util.beanutil.codegen";
    static final String classNamePrefix = "CGGetSet";
    static final String creatorCode = "package " + pkg + ";" +
            "public final class " + classNamePrefix + "? implements " + GetAndSet.class.getName() + "{" +
            "@Override public Object invokeGet(Object obj){return ((?)obj).?();}" +
            "@Override public void invokeSet(Object obj, Object arg){((?)obj).?((?)arg);}" +
            "}";

    public static GetAndSet getObject(Field field) {
        Class<?> clazz = field.getDeclaringClass();
        long idx = index.getAndIncrement();
        String fullClassName = pkg + "." + classNamePrefix + idx;
        String sourceCode = StringUtil.formatQ(creatorCode, idx, clazz.getName(), ClassUtil.getterMethodName(field),
                clazz.getName(), ClassUtil.setterMethodName(field), field.getType().getName());
        try {
            return (GetAndSet) CompileUtil.compile(fullClassName, sourceCode).newInstance();
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }
}
